package com.sunfeng.heima.chap1;

import com.sunfeng.TimeUtils;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 而中断操作是一种简便的线程间交互 方式，而这种交互方式最适合用来取消或停止任务。除了中断以外，还可以利用一个boolean变 量来控制是否需要停止任务并终止该线程。
 * <p>
 * 如何优雅的停止一线程
 * 示例在执行过程中，main线程通过中断操作和cancel()方法均可使CountThread得以终止。
 * 这种通过标识位或者中断操作的方式能够使线程在终止时有机会去清理资源，而不是武断地 将线程停止，因此这种终止线程的做法显得更加安全和优雅。
 */
public class Shutdown {

    public static Object lock = new Object();

    public static void main(String[] args) {

        test2();

        Runner runner = new Runner();
        Thread countThread = new Thread(runner, "CountThread");
        // 睡眠1秒，main线程对CountThread进行中断，使CountThread能够感知中断而结束
        countThread.start();
        TimeUtils.sleep(2);
        countThread.interrupt();

        Runner two = new Runner();
        countThread = new Thread(two, "CountThread");
        countThread.start();
        // 睡眠1秒，main线程对Runner two进行取消，使CountThread能够感知on为false而结束
        TimeUtils.sleep(2);
        two.cancel();
        RunnerWait runnerWait = new RunnerWait();
        Thread runnerWaitThread = new Thread(runnerWait, "runnerWait");
        runnerWaitThread.start();
        TimeUtils.sleep(1);
        runnerWaitThread.interrupt();

    }

    private static class Runner implements Runnable {

        private long i;
        private volatile boolean on = true;

        @Override
        public void run() {
            while (on && !Thread.currentThread().isInterrupted()) {
                i++;
            }
            System.out.println(Thread.currentThread().isInterrupted());
            System.out.println("Count i=" + i);
        }

        public void cancel() {
            on = false;
        }
    }

    /**
     * 如果线程是在sleep  join 或者 wait 中被打断 则会抛出InterruptedException异常
     * <p>
     * 该线程必须事先处理好此异常，由开发者处理，从而提早的终结被阻塞状态   中断位会被重置
     */
    private static class RunnerWait implements Runnable {

        @Override
        public void run() {
            try {
                synchronized (lock) {
                    lock.wait();
                }
            } catch (InterruptedException e) {
                //中断位被设置了false
                System.out.println("RunnerWait :" + Thread.currentThread().isInterrupted());

            }
        }
    }


    private static void test1() {
        new Thread(() -> {
            synchronized (lock) {
                TimeUtils.sleep(10);
            }
        }).start();
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("线程获取到了锁");
            }
            System.out.println("线程完成了执行操作");
        });


        thread1.start();
        TimeUtils.sleep(1);
        //线程是不会被打断的
        thread1.interrupt();

    }

    private static void test2() {
        ReentrantLock reentrantLock = new ReentrantLock();
        new Thread(() -> {
            try {
                reentrantLock.lockInterruptibly();
                TimeUtils.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        }).start();
        Thread thread1 = new Thread(() -> {
            try {
                reentrantLock.lockInterruptibly();
            } catch (InterruptedException e) {
                System.out.println("线程被打断了");
            }
            System.out.println("线程完成了执行操作");
        });


        thread1.start();
        TimeUtils.sleep(1);
        //线程是不会被打断的
        thread1.interrupt();

    }

}
